﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Text;
using System.Collections;
using System.IO;


namespace JavaScriptCodeBehind
{

    public class UserControl : System.Web.UI.UserControl
    {

        protected string arrayName = "JSCB$MetaProgrammingDataArray";
       
        protected Hashtable metaProgrammingDataArray
        {
            get 
            {
                if (Session[this.arrayName] == null)
                    Session[this.arrayName] = new Hashtable();

                return (Hashtable)Session[this.arrayName];
            }
            set
            {
                Session[this.arrayName] = value;
            }
        }

        protected override void OnPreRender(EventArgs e)
        {

            base.OnPreRender(e);

            // Registra o script Library.js...
            ScriptManager.RegisterClientScriptResource(this.Page, typeof(JavaScriptCodeBehind.Page), "JavaScriptCodeBehind.Library.js");

            // Obtém o caminho do local onde está o arquivo .ascx...
            string jsFileName = Path.ChangeExtension(this.ResolveUrl(((System.Web.UI.TemplateControl)this).AppRelativeVirtualPath), "js");

            if (!File.Exists(Server.MapPath(jsFileName)))
            {
                throw new Exception("The JavaScriptCodeBehind file was not found (" + jsFileName + ")");
            }

            // Se o arquivo .js não foi registrado na página...
            if (!this.Page.ClientScript.IsClientScriptIncludeRegistered(this.GetType().BaseType.Name + "_js"))
            {
                // Registra o arquivo .js na página...
                ScriptManager.RegisterClientScriptInclude(this, this.GetType(), this.GetType().BaseType.Name + "_js", jsFileName);
            }

            this.CreateMetaProgrammingDataArray();

            StringBuilder script = new StringBuilder();

            if (!(this.Page is JavaScriptCodeBehind.Page))
                this.RegisterMetaProgrammingDataArray();

            script = new StringBuilder();
            script.Append("<script type='text/javascript'>\n");
            script.Append("//<![CDATA[\n");
            script.Append("  if (typeof(Sys) === 'undefined') throw new Error('ASP.NET Ajax client-side framework failed to load or ScriptManager not found.');\n");
            script.Append("  Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(JavaScriptCodeBehind.Finalize);\n");
            script.Append("  Sys.WebForms.PageRequestManager.getInstance().add_endRequest(JavaScriptCodeBehind.Initialize);\n");
            script.Append("  JavaScriptCodeBehind.Initialize();\n");
            script.Append("//]]>\n");
            script.Append("</script>");

            this.Page.ClientScript.RegisterStartupScript(this.Page.GetType(), "jscb_initialization", script.ToString());

        }

        protected ControlReferenceList ControlsReference = null;

        protected virtual void AddControlReference(Control control)
        {       
            this.AddControlReference(control, true);
        }

        protected virtual void AddControlReference(Control control, bool recusive)
        {
            if (this.ControlsReference == null)
            {
                this.ControlsReference = new ControlReferenceList();
            }

            if (!(control is JavaScriptCodeBehind.UserControl))
            {
                if (this.ControlsReference.IndexOf(control) < 0)
                {
                    this.ControlsReference.Add(new ControlReference(control, recusive));
                }
            }
        }

        protected virtual void CreateMetaProgrammingDataArray()
        {

            MetaProgrammingData _metaProgrammingData = this.MakeBranch(this);
            _metaProgrammingData.isRoot = true;

            if (this.ControlsReference != null)
            {
                for (int i = 0; i < this.ControlsReference.Count; i++)
                {
                    Control control = this.ControlsReference[i].control;
                    _metaProgrammingData = this.MakeBranch(control);
                    _metaProgrammingData.inRoot = true;

                    if (this.ControlsReference[i].recursive)
                        this.RecursiveCreateMetaProgrammingDataArray(_metaProgrammingData);
                }
            }
        }

        protected virtual void RecursiveCreateMetaProgrammingDataArray(MetaProgrammingData metaProgrammingData)
        {
            for (int i = 0; i < metaProgrammingData.control.Controls.Count; i++)
            {
                if (!(metaProgrammingData.control.Controls[i] is JavaScriptCodeBehind.UserControl))
                {
                    MetaProgrammingData _metaProgrammingData = this.MakeBranch(metaProgrammingData.control.Controls[i]);
                    this.RecursiveCreateMetaProgrammingDataArray(_metaProgrammingData);
                }
            }
        }

        protected virtual MetaProgrammingData MakeBranch(Control control)
        {
            if (control is System.Web.UI.Page)
            {
                MetaProgrammingData _metaProgrammingData;
                if (this.metaProgrammingDataArray["Page"] == null)
                {
                    _metaProgrammingData = new MetaProgrammingData(control);
                    _metaProgrammingData.isRoot = true;
                    this.metaProgrammingDataArray.Add("Page", _metaProgrammingData);
                }
                else
                {
                    _metaProgrammingData = (MetaProgrammingData)this.metaProgrammingDataArray[control.ID == "__Page" ? "Page" : control.ID];
                }
                return _metaProgrammingData;
            }
            else
            {
                MetaProgrammingData _metaProgrammingData = MakeBranch(control.NamingContainer);
                MetaProgrammingData __metaProgrammigData;
                string aux = control.ClientID;
                if (_metaProgrammingData.hashTable[control.ID] == null)
                {
                    __metaProgrammigData = new MetaProgrammingData(control);
                    _metaProgrammingData.hashTable.Add(control.ID, __metaProgrammigData);
                }
                else
                {
                    __metaProgrammigData = (MetaProgrammingData)_metaProgrammingData.hashTable[control.ID];
                }
                return __metaProgrammigData;
            }
        }

        protected virtual void RegisterMetaProgrammingDataArray()
        {
            ArrayList keys = new ArrayList(this.metaProgrammingDataArray.Keys);
            MetaProgrammingData metaProgrammingData = (MetaProgrammingData)this.metaProgrammingDataArray[keys[0]];
            ScriptManager.RegisterArrayDeclaration(this.Page, this.arrayName, metaProgrammingData.ToString());
            this.metaProgrammingDataArray.Clear();
            this.metaProgrammingDataArray = null;
        }
        
    }
}